#pragma once 
#include <iostream>
#include <string>
#include <pthread.h>

using namespace std;

enum class Status
{
    NEW = 0,
    RUNNING,
    EXIT 
};

typedef void (*func_t)(void*);

class Thread
{
public:
    Thread(int num = 0, func_t func = nullptr, void* args = nullptr)
        :_tid(0), _status(Status::NEW), _func(func), _args(args)
         {
            char name[128];
            snprintf(name, sizeof(name), "thread-%d", num);
            _name = name;
         }
    
    pthread_t getTID() const
    {
        return _tid;
    }

    std::string getName() const 
    {
        return _name; 
    }

    Status getStatus() const 
    {
        return _status; 
    }

    void run()
    {
        int ret = pthread_create(&_tid, nullptr, runHelper, this);
        if(ret != 0)
        {
            std::cerr << "creat thread fail!" << endl;
            exit(1);
        }
        _status = Status::RUNNING; 
    }

    static void* runHelper(void* args)
    {
        Thread* myThis = static_cast<Thread*>(args);
        myThis->_func(myThis->_args);
        return nullptr;
    }

    void join()
    {
        int ret = pthread_join(_tid, nullptr);
        if(ret != 0)
        {
            std::cerr << "thread join fail!" << endl;
            exit(1);
        }
        _status = Status::EXIT;
    }

private:
    pthread_t _tid;
    std::string _name;
    Status _status;
    func_t _func;
    void* _args;
};
